package com.spzx.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.core.utils.bean.BeanUtils;
import com.spzx.product.api.domain.VO.CategoryVO;
import com.spzx.product.api.domain.Category;
import com.spzx.domain.CategoryExcelListener;
import com.spzx.mapper.CategoryMapper;
import com.spzx.service.CategoryService;
import jakarta.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    @Override
    public List<Category> getListByFatherId(Long id) {
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", id);
        List<Category> list = this.list(queryWrapper);
        list.forEach(category -> {
            if (this.count(Wrappers.lambdaQuery(Category.class).eq(Category::getParentId, category.getId())) > 0) {

                category.setHasChildren(true);
            } else {
                category.setHasChildren(false);
            }
        });
        return list;
    }

    @Override
    public List<Long> getFatherIdList(Long id) {
        List<Long> list = new ArrayList<>();
        Long ids = id;
        for (; ids > 0; ) {
            list.add(ids);
            ids = this.getOne(Wrappers.lambdaQuery(Category.class).eq(Category::getId, ids)).getParentId();
        }
        return list;
    }

    @Override
    public String getNameById(Long id) {

        return this.getOne(Wrappers.lambdaQuery(Category.class).eq(Category::getId, id)).getName();

    }

    @Override
    public boolean importCategory(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            if (inputStream.available() == 0) {
                throw new ServiceException("文件大小异常");

            }
            String fileName = file.getOriginalFilename().toLowerCase();
            if (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls") && !fileName.endsWith(".csv")) {
                throw new ServiceException("文件格式有误");
            }
            EasyExcel
                    .read(inputStream)
                    .head(Category.class)
                    .registerReadListener(new CategoryExcelListener(this))
                    .sheet(0)
                    .doRead();
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return true;
    }

    @Override
    public Boolean exists(Category category) {
        if (this.count(Wrappers.lambdaQuery(Category.class).eq(Category::getId, category.getId())) > 0
                ||
                this.count(Wrappers.lambdaQuery(Category.class).eq(Category::getParentId, category.getParentId())
                        .eq(Category::getName, category.getName())) > 0) {
            return true;
        }
        return false;
    }

    @Override
    public void exportCategory(HttpServletResponse response) {
        try {
            List<Category> categoryList = this.list();
            String fileName = URLEncoder.encode("分类列表" + new DateTime().toString("yyyy年MM月dd日HH时mm分SS秒") + ExcelTypeEnum.XLSX.getValue(), "UTF-8");
            response.setHeader("content-disposition", "attachment;filename=" + fileName);

            EasyExcel.write(response.getOutputStream()).head(Category.class).sheet().doWrite(categoryList);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void importTemplate(HttpServletResponse response) {
        try {
            List<Category> categoryList = new ArrayList<>();
            String fileName = URLEncoder.encode("模板" + ExcelTypeEnum.XLSX.getValue(), "UTF-8");
            response.setHeader("content-disposition", "attachment;filename=" + fileName);

            EasyExcel.write(response.getOutputStream()).head(Category.class).sheet().doWrite(categoryList);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<CategoryVO> getFirstCategoryList(long id) {
        List<Category> listByFatherId = this.getListByFatherId(0L);
        List<CategoryVO> collect = turnToVo(listByFatherId);
        return collect;
    }

    @Override
    public List<CategoryVO> getCategoryTree() {
        List<Category> firstCategoryList = this.getListByFatherId(0L);
        List<CategoryVO> categoryVOS = turnToVo(firstCategoryList);
        List<CategoryVO> collect = categoryVOS.stream().map(categoryVO -> {
            List<Category> categories = this.getListByFatherId(categoryVO.getId());
            List<CategoryVO> categoryVOS1 = turnToVo(categories);
            categoryVOS1.stream().map(categoryVO2 -> {
                List<Category> categories2 = this.getListByFatherId(categoryVO2.getId());
                List<CategoryVO> categoryVOS2 = turnToVo(categories2);
                categoryVO2.setChildren(categoryVOS2);
                return categoryVO2;
            }).collect(Collectors.toList());
            categoryVO.setChildren(categoryVOS1);
            return categoryVO;
        }).collect(Collectors.toList());

        return collect;
    }

    private static List<CategoryVO> turnToVo(List<Category> categoryList) {
        List<CategoryVO> collect = categoryList.stream()
                .map(category -> {
                    CategoryVO categoryVO = new CategoryVO();
                    BeanUtils.copyProperties(category, categoryVO);
                    return categoryVO;
                })
                .collect(Collectors.toList());
        return collect;
    }
}
